home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / commands.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  21KB  |  822 lines

  1. /*
  2.  * Command parser
  3.  */
  4.  
  5. #include <global.h>
  6. #include <commands.h>
  7. #include <sproto.h>
  8. #include <ctype.h>
  9. #include <X11/keysym.h>
  10.  
  11. /* Added times to all the commands.  However, this was quickly done,
  12.  * and probably needs more refinements.  All socket and DM commands
  13.  * take 0 time.
  14.  */
  15.  
  16.  
  17. /*
  18.  * Normal game commands
  19.  */
  20. CommArray_s Commands[] = {
  21.   {"save", command_save,    0.0},
  22. #ifdef SAVE_WINDOW_POSITIONS
  23.   {"savewinpos", command_savewinpos,    0.0},
  24. #endif /* SAVE_WINDOW_POSITIONS */
  25.  
  26. #ifdef SOUND_EFFECTS
  27.   {"sound", command_sound,    0.0},
  28. #endif
  29. #ifdef SIMPLE_PARTY_SYSTEM
  30.   {"party", command_party,    0.0},
  31.   {"gsay", command_gsay,    1.0},
  32. #endif
  33.  
  34. #ifdef DEBUG
  35.   {"sstable", command_sstable,    0.0},
  36. #endif
  37. #ifdef DEBUG_MALLOC_LEVEL
  38.   {"verify", command_malloc_verify,0.0},
  39. #endif
  40.   {"add", command_add,        0.0},
  41.   {"apply", command_apply,    1.0},    /* should be variable */
  42.   {"archs", command_archs,    0.0},
  43.   {"bell", command_bell,    0.0},
  44.   {"berzerk", command_berzerk,    0.0},
  45.   {"bind", command_bind,    0.0},
  46.   {"brace", command_brace,    0.0},
  47.   {"cast", command_cast,    0.0},    /* Is this right? */
  48.   {"clearinfo", command_clearinfo,0.0},
  49.   {"disarm", command_disarm,    1.0},
  50.   {"dm", command_dm,        0.0},
  51.   {"drop", command_drop,    1.0},
  52.   {"dropall", command_dropall,    1.0},
  53.   {"examine", command_examine,    0.5},
  54.   {"get", command_take,        1.0},
  55.   {"help", command_help,    0.0},
  56.   {"hiscore", command_hiscore,    0.0},
  57.   {"inv-lock", command_lock,    0.0},
  58.   {"inv-unlock", command_unlock,0.0},
  59.   {"inventory", command_inventory,0.0},
  60.   {"invoke", command_invoke,    1.0},
  61.   {"keyboard", command_keyboard_flush,0.0},
  62.   {"last", command_last,    0.0},
  63.   {"listen", command_listen,    0.0},
  64.   {"malloc", command_malloc,    0.0},
  65.   {"maps", command_maps,    0.0},
  66.   {"mapinfo", command_mapinfo,    0.0},
  67.   {"motd", command_motd,    0.0},
  68.   {"output-sync", command_output_sync,    0.0},
  69.   {"output-count", command_output_count,0.0},
  70.   {"peaceful", command_peaceful,0.0},
  71.   {"pickup", command_pickup,    1.0},
  72.   {"prepare", command_prepare,    1.0},
  73.   {"quit", command_quit,    0.0},
  74.   {"refresh", command_refresh,    0.0},
  75.   {"rotateinventory", command_rotateinventory,    0.0},
  76.   {"rotateshoottype", command_rotateshoottype,    0.0},
  77.   {"rotatespells", command_rotatespells,    0.0},
  78.   {"say", command_say,        0.0},
  79.   {"scroll", command_scroll,    0.0},
  80.   {"shout", command_shout,    0.0},
  81.   {"show", command_show,    0.0},
  82.   {"showinvicon", command_show_inv_icon, 0.0},
  83. #ifdef ALLOW_SKILLS
  84.   {"skills", command_skills,    0.0},    /* shows player list of skills */
  85.   {"use_skill", command_uskill, 0.0},
  86.   {"ready_skill", command_rskill, 0.0},
  87. #endif
  88.   {"search",command_search,    1.0},
  89. #ifdef SEARCH_ITEMS
  90.   {"search-items", command_search_items,    0.0},
  91. #endif
  92.   {"strength", command_strength,    0.0},
  93.   {"strings", command_strings,    0.0},
  94.   {"sync", command_sync,    0.0},
  95.   {"take", command_take,    1.0},
  96.   {"tell", command_tell,    0.0},
  97.   {"throw", command_throw,    0.0},
  98.   {"time", command_time,    0.0},
  99. #ifdef SET_TITLE
  100.   {"title", command_title,    0.0},
  101. #endif
  102.   {"unbind", command_unbind,    0.0},
  103.   {"version", command_version,    0.0},
  104.   {"wimpy", command_wimpy,    0.0},
  105.   {"who", command_who,        0.0},
  106.  
  107.   {"stay", command_stay,    0.0},
  108.   {"north", command_north,    1.0},
  109.   {"east", command_east,    1.0},
  110.   {"south", command_south,    1.0},
  111.   {"west", command_west,    1.0},
  112.   {"northeast", command_northeast,    1.0},
  113.   {"southeast", command_southeast,    1.0},
  114.   {"southwest", command_southwest,    1.0},
  115.   {"northwest", command_northwest,    1.0},
  116. };
  117.  
  118. const int CommandsSize =sizeof(Commands) / sizeof(CommArray_s);
  119.  
  120. CommArray_s NewServerCommands [] = {
  121.   {"run", command_run, 1.0},
  122.   {"run_stop", command_run_stop, 0.0},
  123.   {"fire", command_fire, 1.0},
  124.   {"fire_stop", command_fire_stop, 0.0}
  125. };
  126.  
  127. const int NewServerCommandSize = sizeof(NewServerCommands)/ sizeof(CommArray_s);
  128.  
  129. /*
  130.  * And alternative socket commands
  131.  */
  132. CommArray_s SocketCommands [] = {
  133.   {"add", command_add,0.0},
  134.   {"archs", command_archs,0.0},
  135.   {"bell", command_bell,0.0},
  136.   {"dm", command_dm,0.0},
  137.   {"help", command_help,0.0},
  138.   {"hiscore", command_hiscore,0.0},
  139.   {"listen", command_listen,0.0},
  140.   {"malloc", command_malloc,0.0},
  141.   {"maps", command_maps,0.0},
  142.   {"name", command_name,0.0},
  143.   {"protocol", command_protocol,0.0},
  144.   {"quit", command_quit,0.0},
  145.   {"set", command_set,0.0},
  146.   {"shout", command_shout,0.0},
  147.   {"strings", command_strings,0.0},
  148.   {"sync", command_sync,0.0},
  149.   {"tell", command_tell,0.0},
  150.   {"time", command_time,0.0},
  151.   {"unset", command_unset,0.0},
  152.   {"version", command_version,0.0},
  153.   {"who", command_who,0.0},
  154. };
  155.  
  156. const int SocketCommandsSize =sizeof(SocketCommands) / sizeof(CommArray_s);
  157.  
  158. /*
  159.  * Wizard commands (for both)
  160.  */
  161. CommArray_s WizCommands [] = {
  162.   {"abil", command_abil,0.0},
  163.   {"addexp", command_addexp,0.0},
  164.   {"create", command_create,0.0},
  165.   {"debug", command_debug,0.0},
  166.   {"dump", command_dump,0.0},
  167.   {"dumpbelow", command_dumpbelow,0.0},
  168.   {"dumpfriendlyobjects", command_dumpfriendlyobjects,0.0},
  169.   {"dumplights", command_dumplights,0.0},
  170.   {"dumpallarchetypes", command_dumpallarchetypes,0.0},
  171.   {"dumpallmaps", command_dumpallmaps,0.0},
  172.   {"dumpallobjects", command_dumpallobjects,0.0},
  173.   {"dumpmap", command_dumpmap,0.0},
  174.   {"free", command_free,0.0},
  175.   {"goto", command_goto,0.0},
  176.   {"invisible", command_invisible,0.0},
  177.   {"nodm", command_nowiz,0.0},
  178.   {"nowiz", command_nowiz,0.0},
  179.   {"patch", command_patch,0.0},
  180.   {"printlos", command_printlos,0.0},
  181.   {"remove", command_remove,0.0},
  182.   {"reset", command_reset,0.0},
  183.   {"speed", command_speed,0.0},
  184.   {"spellreset", command_spell_reset,0.0},
  185.   {"ssdumptable", command_ssdumptable,0.0},
  186.   {"stats", command_stats,0.0},
  187.   {"summon", command_summon,0.0},
  188.   {"wizpass", command_wizpass,0.0},
  189. };
  190.  
  191. const int WizCommandsSize =sizeof(WizCommands) / sizeof(CommArray_s);
  192.  
  193.  
  194.  
  195. static int compare_A(const void *a, const void *b)
  196. {
  197.   return strcmp(((CommArray_s *)a)->name, ((CommArray_s *)b)->name);
  198. }
  199.  
  200. void init_commands()
  201. {
  202.   qsort((char *)Commands, CommandsSize, sizeof(CommArray_s), compare_A);
  203.   qsort((char *)WizCommands, WizCommandsSize, sizeof(CommArray_s), compare_A);
  204.   qsort((char *)SocketCommands, SocketCommandsSize, sizeof(CommArray_s), compare_A);
  205.   qsort((char *)NewServerCommands, NewServerCommandSize, sizeof(CommArray_s), compare_A);
  206. }
  207.  
  208. #ifndef tolower
  209. #define tolower(C)    (((C) >= 'A' && (C) <= 'Z')? (C) - 'A' + 'a': (C))
  210. #endif
  211.  
  212.  
  213. static CommFunc find_command(char *cmd)
  214. {
  215.   CommArray_s *asp, dummy;
  216.   char *cp;
  217.  
  218.   for (cp=cmd; *cp; cp++)
  219.     *cp =tolower(*cp);
  220.  
  221.   dummy.name =cmd;
  222.   asp =(CommArray_s *)bsearch((void *)&dummy,
  223.                   (void *)Commands, CommandsSize,
  224.                   sizeof(CommArray_s), compare_A);
  225.   if (asp)
  226.     return asp->func;
  227.   return NULL;
  228. }
  229.  
  230. static CommFunc find_wizcommand(char *cmd)
  231. {
  232.   CommArray_s *asp, dummy;
  233.   char *cp;
  234.  
  235.   for (cp=cmd; *cp; cp++)
  236.     *cp =tolower(*cp);
  237.  
  238.   dummy.name =cmd;
  239.   asp =(CommArray_s *)bsearch((void *)&dummy,
  240.                   (void *)WizCommands, WizCommandsSize,
  241.                   sizeof(CommArray_s), compare_A);
  242.   if (asp)
  243.     return asp->func;
  244.   return NULL;
  245. }
  246.  
  247. static CommFunc find_socketcommand(char *cmd)
  248. {
  249.   CommArray_s *asp, dummy;
  250.   char *cp;
  251.  
  252.   for (cp=cmd; *cp; cp++)
  253.     *cp =tolower(*cp);
  254.  
  255.   dummy.name =cmd;
  256.   asp =(CommArray_s *)bsearch((void *)&dummy,
  257.                   (void *)SocketCommands, SocketCommandsSize,
  258.                   sizeof(CommArray_s), compare_A);
  259.   if (asp)
  260.     return asp->func;
  261.   return NULL;
  262. }
  263.  
  264. long xfire_kc2ks(player *p,KeyCode kc,long foozit)
  265. {
  266.   if (p->eric_server == 0) {
  267.     return XKeycodeToKeysym(p->gdisp,kc,foozit);
  268.   } else {
  269.     return NoSymbol; /* esrv stuff doesn't deal with foozit -- I don't care*/
  270.   }
  271. }
  272.  
  273. long xfire_ks2kc(player *p,KeySym ks)
  274. {
  275.   if (p->eric_server>0) {
  276.     return esrv_ks2kc(p->eric_server,ks);
  277.   } else {
  278.     return XKeysymToKeycode(p->gdisp,ks);
  279.   }
  280. }
  281.  
  282. void insert_key_complex(player *p, KeySym ks, KeyCode keycode, int flags, char* line)
  283. {
  284.   int ix, len;
  285.   char *cp;
  286.   Key_s *newkey =(Key_s *)malloc(sizeof(Key_s));
  287.   
  288.  
  289. #ifdef INPUT_DEBUG
  290.   if (line)
  291.     fprintf(stderr, "%i: %s (%i) 0x%x '%s'\n",
  292.       (int)p, ((cp=XKeysymToString(ks))? cp: "(null)"), (int)keycode, flags, line);
  293.   else
  294.     fprintf(stderr, "%i: %s (%i) 0x%x (null)\n",
  295.     (int)p, ((cp=XKeysymToString(ks))? cp: "(null)"), (int)keycode, flags);
  296. #endif
  297.  
  298.   if (!(newkey))
  299.     fatal(OUT_OF_MEMORY);
  300.  
  301.   if (ks != NoSymbol &&
  302.       ks != xfire_kc2ks(p, keycode, 0) &&
  303.       ks != xfire_kc2ks(p, keycode, ShiftMask))
  304.     keycode =xfire_ks2kc(p, ks);
  305.  
  306.   ix = (int)(keycode) % COMMAND_HASH_SIZE;
  307.   newkey->keysym  =ks;
  308.   newkey->keycode =keycode;
  309.   newkey->flags   =flags;
  310.   newkey->next    =p->keys[ix];
  311.   newkey->params  =NULL;
  312.  
  313.   if (flags & KEYF_EDIT) {
  314.     newkey->func =NULL;
  315.     if (!line) {
  316.       free(newkey);
  317.       return;
  318.     }
  319.     cp =line;
  320.   } else {            /* KEYF_EDIT */
  321.     if (!line) {
  322.       newkey->func =NULL;
  323.       p->keys[ix] =newkey;
  324.       return;
  325.     }
  326.     if ((cp=strchr(line, ' '))) {
  327.       *(cp++) ='\0';
  328.       if (!(newkey->func=find_command(line))) {
  329.     cp[-1] =' ';
  330.     cp =line;
  331.       }
  332.     } else {            /* ' ' */
  333.       if ((newkey->func=find_command(line))) {
  334.     p->keys[ix] =newkey;
  335.     return;
  336.       }    
  337.       cp =line;
  338.     }                /* ' ' */
  339.   }                /* KEYF_EDIT */
  340.   len =strlen(cp);
  341.   if (len && cp[len-1] == '\n')
  342.     cp[--len] ='\0';
  343.   newkey->params =(char *)malloc(len+1);
  344.   if (!newkey->params)
  345.     fatal(OUT_OF_MEMORY);
  346.   memcpy(newkey->params, cp, len+1);
  347.   p->keys[ix] =newkey;
  348. }
  349.  
  350. void insert_key(player *p, int baseflags, char *text)
  351. {
  352.   char *tmp;
  353.   int nro, flags, len;
  354.  
  355.   if (!(tmp=strchr(text, ' '))) {
  356.     LOG(llevError, "Corrupted keysym in %s\n", text);
  357.     return;
  358.   }
  359.   *(tmp++) ='\0';
  360.   if (!(nro=strtol(tmp, NULL, 10))) {
  361.     nro= xfire_ks2kc(p, XStringToKeysym(text));
  362.     if (nro==0 && p->eric_server<1) {
  363.     LOG(llevError, "Corrupted keycode in %s\n", tmp);
  364.     return;
  365.     }
  366.   }
  367.   if (!(tmp=strchr(tmp, ' '))) {
  368.     LOG(llevError, "Corrupted flags in %s\n", text);
  369.     return;
  370.   }
  371.   flags =baseflags;
  372.   tmp++;
  373.   while (*tmp != ' ' && *tmp != '\n' && *tmp != '\0') {
  374.     switch (*tmp) {
  375.     case 'A':
  376.       flags |= KEYF_NORMAL | KEYF_FIRE | KEYF_RUN;
  377.       break;
  378.     case 'N':
  379.       flags |= KEYF_NORMAL;
  380.       break;
  381.     case 'F':
  382.       flags |= KEYF_FIRE;
  383.       break;
  384.     case 'R':
  385.       flags |= KEYF_RUN;
  386.       break;
  387.     case 'E':
  388.       flags |= KEYF_EDIT;
  389.       break;
  390.     default:
  391.       LOG(llevError, "Corrupted flags in %s\n", text);
  392.       return;
  393.     }
  394.     tmp++;
  395.   }
  396.  
  397.   len =strlen(tmp);
  398.   if (len && tmp[--len] == '\n')
  399.     tmp[len] ='\0';
  400.  
  401.   if (*tmp != ' ')
  402.     insert_key_complex(p, XStringToKeysym(text), (KeyCode)nro, flags, NULL);
  403.   else
  404.     insert_key_complex(p, XStringToKeysym(text), (KeyCode)nro, flags, tmp+1);
  405. }
  406.  
  407.  
  408. void load_default_keys(player *p)
  409. {
  410.   FILE *fp;
  411.   char filename[MAX_BUF], line[MAX_BUF];
  412.   int i;
  413.  
  414.   p->commandkeysym =XK_apostrophe;
  415.   p->commandkey =xfire_ks2kc(p, XK_apostrophe);
  416.   if (!p->commandkey) {
  417.     p->commandkeysym =XK_acute;
  418.     p->commandkey =xfire_ks2kc(p, XK_acute);
  419.   }
  420.   p->firekeysym[0] =XK_Shift_L;
  421.   p->firekey[0] =xfire_ks2kc(p, XK_Shift_L);
  422.   p->firekeysym[1] =XK_Shift_R;
  423.   p->firekey[1] =xfire_ks2kc(p, XK_Shift_R);
  424.   p->runkeysym[0]  =XK_Control_L;
  425.   p->runkey[0]  =xfire_ks2kc(p, XK_Control_L);
  426.   p->runkeysym[1]  =XK_Control_R;
  427.   p->runkey[1]  =xfire_ks2kc(p, XK_Control_R);
  428.  
  429.   for(i=0;i<COMMAND_HASH_SIZE;i++)
  430.     while (p->keys[i]) {
  431.       Key_s *kp =p->keys[i];
  432.       if (kp->params)
  433.     free(kp->params);
  434.       p->keys[i] =kp->next;
  435.       free(kp);
  436.     }
  437.   
  438.   sprintf(filename, "%s/def_keys", LibDir);
  439.   
  440.   if ((fp=fopen(filename, "r")) == NULL) {
  441.     LOG(llevError, "Can't open %s\n", filename);
  442.     perror("Can't read default keys");
  443.     return;
  444.   }
  445.   
  446.   while (fgets(line, MAX_BUF, fp))
  447.     if (line[0] != '#' && line[0] != '\n') {
  448.       line[MAX_BUF-1] ='\0';
  449.       insert_key(p, KEYF_DEFAULT, line);
  450.     }
  451.   
  452.   fclose(fp);
  453. }
  454.  
  455.  
  456. char *find_func_name(CommFunc func)
  457. {
  458.   int i;
  459.  
  460.   for (i=0; i<CommandsSize; i++)
  461.     if (Commands[i].func == func)
  462.       return Commands[i].name;
  463.   return "(null)";
  464. }
  465.  
  466.  
  467. void dump_keys(player *p, FILE *fp)
  468. {
  469.   int i, bi;
  470.   Key_s *key, *prev, *prev2;
  471.   char buff[4];
  472.  
  473.   for (i=0; i<COMMAND_HASH_SIZE; i++) {
  474.     /* find bottom entry */
  475.     for (prev=NULL,key=p->keys[i];
  476.      key && !(key->flags & KEYF_DEFAULT);
  477.      key =key->next)
  478.       prev =key;
  479.  
  480.     /* from buttom -> up */
  481.     while (prev) {
  482.       if (prev->flags & KEYF_WIZ)
  483.     continue;
  484.       if(prev->keysym == NoSymbol)
  485.     fprintf(fp, "key (null) %i ", prev->keycode);
  486.       else
  487.     fprintf(fp, "key %s %i ", XKeysymToString(prev->keysym),prev->keycode);
  488.       buff[0] ='\0'; buff[1] ='\0'; buff[2] ='\0'; buff[3] ='\0';
  489.       bi =0;
  490.       if ((prev->flags & (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN)) ==
  491.       (KEYF_NORMAL|KEYF_FIRE|KEYF_RUN))
  492.     buff[bi++] ='A';
  493.       else {
  494.     if (prev->flags & KEYF_NORMAL)
  495.       buff[bi++] ='N';
  496.     if (prev->flags & KEYF_FIRE)
  497.       buff[bi++] ='F';
  498.     if (prev->flags & KEYF_RUN)
  499.       buff[bi++] ='R';
  500.       }
  501.       if (prev->flags & KEYF_EDIT)
  502.     buff[bi++] ='E';
  503.       if (prev->func)
  504.     if (prev->params)
  505.       fprintf(fp, "%s %s %s\n", buff, find_func_name(prev->func), prev->params);
  506.     else
  507.       fprintf(fp, "%s %s\n", buff, find_func_name(prev->func));
  508.       else
  509.     if (prev->params)
  510.       fprintf(fp, "%s %s\n", buff, prev->params);
  511.     else
  512.       fprintf(fp, "%s\n", buff);
  513.  
  514.       /* step one up */
  515.       for (prev2=NULL,key=p->keys[i]; key != prev; key =key->next)
  516.     prev2 =key;
  517.       prev =prev2;
  518.     }                /* while prev */
  519.   }                /* for i */
  520. }
  521.  
  522. void configure_keys(object *op, KeyCode k, KeySym keysym)
  523. {
  524.   int flags;
  525.   char *cp;
  526.  
  527.   if (op->contr->write_buf[0] == 'B' || 
  528.       op->contr->write_buf[0] == 'U') {
  529.     if(k == op->contr->firekey[0] || k == op->contr->firekey[1]) {
  530.       op->contr->fire_on =1;
  531.       return;
  532.     }
  533.     if(k == op->contr->runkey[0] || k == op->contr->runkey[1]) {
  534.       op->contr->run_on =1;
  535.       return;
  536.     }
  537.   }
  538.   
  539.   op->contr->state = ST_PLAYING;
  540.  
  541.   switch (op->contr->write_buf[0]) {
  542.   case 'C':
  543.     op->contr->commandkey =k;
  544.     op->contr->commandkeysym =keysym;
  545.     goto done;
  546.   case 'F':
  547.     op->contr->firekey[0] =k;
  548.     op->contr->firekeysym[0] =keysym;
  549.     goto done;
  550.   case 'f':
  551.     op->contr->firekey[1] =k;
  552.     op->contr->firekeysym[1] =keysym;
  553.     goto done;
  554.   case 'R':
  555.     op->contr->runkey[0] =k;
  556.     op->contr->runkeysym[0] =keysym;
  557.     goto done;
  558.   case 'r':
  559.     op->contr->runkey[1] =k;
  560.     op->contr->runkeysym[1] =keysym;
  561.     goto done;
  562.   case 'B':
  563.     flags =strtol(op->contr->write_buf+1, &cp, 10);
  564.     if (!cp || !flags) {
  565.       LOG(llevError, "Corrupted line to bind!\n");
  566.       return;
  567.     }
  568.     if (*cp == ' ')
  569.       cp++;
  570.     if (flags & 0x1000)
  571.       insert_key_complex(op->contr, NoSymbol, k, (flags&0xfff)|KEYF_USER, cp);
  572.     else
  573.       insert_key_complex(op->contr, keysym, k, flags|KEYF_USER, cp);
  574.     goto done;
  575.   }
  576.  
  577.   LOG(llevError, "Got to end of configure??\n");
  578.   return;
  579.  
  580.   /*
  581.    * Post config
  582.    */
  583.  done:
  584.   new_draw_info_format(NDI_UNIQUE, 0, op,
  585.     "Binded to key '%s' (%i)", XKeysymToString(keysym), (int)k);
  586.   op->contr->fire_on=0;
  587.   op->contr->run_on=0;
  588.   return;
  589. }
  590.  
  591.  
  592.  
  593.  
  594. /*
  595.  * parse_string may be called from a player in the game or from a socket
  596.  * (op is NULL if it's a socket).
  597.  * It returnes 1 if it recognized the command, otherwise 0.
  598.  * Actually return value is used as can-repeat -flag
  599.  */
  600.  
  601. int parse_string(object *op, char *str)
  602. {
  603.   CommFunc f;
  604.   char *cp;
  605.  
  606. #ifdef INPUT_DEBUG
  607.   LOG(llevDebug, "Command: '%s'\n", str);
  608. #endif
  609.  
  610.   /*
  611.    * No arguments?
  612.    */
  613.   if (!(cp=strchr(str, ' '))) {
  614.     if (!op) {
  615.       if(active_socket == (sockets *) NULL) {
  616.     LOG(llevError,"parse_string without active socket: %s\n",str);
  617.     return 0;
  618.       }
  619.       if ((f=find_socketcommand(str)))
  620.     return f(op, NULL);
  621.       if (active_socket->wiz && (f=find_wizcommand(str)))
  622.     return f(op, NULL);
  623.       new_draw_info_format(NDI_UNIQUE, 0, op, "Unknown command: %s", str);
  624.       return 0;
  625.     } 
  626.     op->contr->writing =0;
  627.     if(!op->contr->no_echo) {
  628.       new_draw_info_format(NDI_UNIQUE, 0, op,
  629.     ">%s", str);
  630.     }
  631.     if ((f=find_command(str)))
  632.       return f(op, NULL);
  633.     if (QUERY_FLAG(op,FLAG_WIZ) && (f=find_wizcommand(str)))
  634.       return f(op, NULL);
  635.  
  636.     if(op) {
  637.       op->contr->no_echo = 0;
  638.       new_draw_info(NDI_UNIQUE, 0,op, "Unknown command.  Try help.");
  639.     }
  640.     return 0;
  641.   }                /* ' ' */
  642.  
  643.   /*
  644.    * Command with some arguments
  645.    */
  646.  
  647.   *(cp++) ='\0';
  648.  
  649.   if (!op) {
  650.     if(active_socket == (sockets *) NULL) {
  651.       LOG(llevError,"parse_string without active socket: %s %s\n",str, cp);
  652.       return 0;
  653.     }
  654.     if ((f=find_socketcommand(str)))
  655.       return f(op, cp);
  656.     if (active_socket->wiz && (f=find_wizcommand(str)))
  657.       return f(op, cp);
  658.     return 0;
  659.   } 
  660.  
  661.   op->contr->writing =0;
  662.   if(!op->contr->no_echo) {
  663.     new_draw_info_format(NDI_UNIQUE, 0, op,
  664.     ">%s %s", str, cp);
  665.   }
  666.   if ((f=find_command(str)))
  667.     return f(op, cp);
  668.   if (QUERY_FLAG(op, FLAG_WIZ) && (f=find_wizcommand(str)))
  669.     return f(op, cp);
  670.  
  671.   if(op) {
  672.     op->contr->no_echo = 0;
  673.     new_draw_info(NDI_UNIQUE, 0,op, "Unknown command.  Try help.");
  674.   }
  675.   return 0;
  676. }
  677.  
  678.  
  679. int parse_writing(object *op, char k)
  680. {
  681.   player *pl=op->contr;
  682.  
  683.   if (k != 13) {
  684.     write_ch(op, k);
  685.     return 1;
  686.   }
  687.  
  688.   if(pl->write_buf[0] != '>')
  689.     LOG(llevError, "Corrupted commandline (%s)\n", pl->write_buf);
  690.  
  691.   pl->write_buf[pl->writing] ='\0';
  692.   return parse_string(op, pl->write_buf+1);
  693. }
  694.  
  695.  
  696. int parse_key(object *op, char k, KeyCode kc, KeySym keysym)
  697. {
  698.   int i, ix;
  699.   Key_s *key;
  700.   player *pl=op->contr;
  701.   static char p_buff[MAX_BUF];
  702.   char *charkey;
  703.  
  704. #ifdef INPUT_DEBUG
  705.  
  706.   if (k >= ' ')
  707.     fprintf(stderr, "Key '%c' Keycode %d Keysym '%s'\n",
  708.     k, (int)kc, XKeysymToString(keysym));
  709.   else
  710.     fprintf(stderr, "Keycode %d Keysym '%s'\n",
  711.     (int)kc, XKeysymToString(keysym));
  712. #endif
  713.  
  714.   if(pl->viewmap) {
  715.     pl->viewmap=0;
  716.     refresh(op);
  717.   }
  718.  
  719.   if (kc == pl->commandkey && keysym == pl->commandkeysym && 
  720.       !pl->writing) {
  721.     write_ch(op,'>');
  722.     pl->count=0;
  723.     return 1;
  724.   }
  725.   if ((kc == pl->firekey[0] && keysym == pl->firekeysym[0]) ||
  726.       (kc == pl->firekey[1] && keysym == pl->firekeysym[1]))
  727.     return pl->fire_on=1;
  728.   if ((kc == pl->runkey[0] && keysym == pl->runkeysym[0]) ||
  729.       (kc == pl->runkey[1] && keysym == pl->runkeysym[1]))
  730.     return pl->run_on=1;
  731.   if(pl->writing) {
  732.     if (keysym != NoSymbol &&
  733.     !(IsKeypadKey(keysym) || IsCursorKey(keysym) || IsPFKey(keysym) ||
  734.       IsFunctionKey(keysym) || IsMiscFunctionKey(keysym) ||
  735.       IsModifierKey(keysym)))
  736.       return parse_writing(op, k);
  737.   }
  738.  
  739.   pl->prev_keycode =kc,
  740.   pl->prev_keysym =keysym,
  741.   pl->prev_cmd =k;
  742.   pl->prev_fire_on =pl->fire_on;
  743.  
  744.   ix =(int)(kc) % COMMAND_HASH_SIZE;
  745.   for (key=pl->keys[ix]; key ; key =key->next) {
  746.     if ((key->keycode != kc) ||
  747.     (key->keysym != NoSymbol && key->keysym != keysym) ||
  748.     (key->flags & KEYF_WIZ && !QUERY_FLAG(op, FLAG_WIZ)) ||
  749.     (pl->fire_on && !(key->flags & KEYF_FIRE)) ||
  750.     (pl->run_on && !(key->flags & KEYF_RUN)) ||
  751.     (!pl->fire_on && !pl->run_on &&
  752.      !(key->flags & KEYF_NORMAL)))
  753.       continue;
  754.     if (key->func) {
  755.       if (key->params) {
  756.     strcpy(p_buff, key->params);
  757.     return (key->func)(op, p_buff);
  758.       }
  759.       return (key->func)(op, NULL);
  760.     }
  761.     if (key->params) {
  762.       if (!(key->flags & KEYF_EDIT))
  763.     return parse_string(op, key->params);
  764.       if (pl->writing)
  765.     return 1;
  766.       write_ch(op, '>');
  767.       for (i=0; key->params[i]; i++)
  768.     write_ch(op, key->params[i]);
  769.       return 1;
  770.     }
  771.     return 1;
  772.   }
  773.  
  774.   if(k >= '0' && k <= '9') {
  775.     pl->count =((k-'0')+(int)pl->count*10) % 100000;
  776.     new_draw_info_format(NDI_UNIQUE, 0, op,
  777.     "Count: %d.", pl->count);
  778.     return 1;
  779.   }
  780.  
  781.   charkey=XKeysymToString(keysym);
  782.   new_draw_info_format(NDI_UNIQUE, 0, op,
  783.     "Key unused (%s%s%s)",
  784.       (pl->fire_on? "Fire&": ""),
  785.       (pl->run_on ? "Run&" : ""),
  786.       (charkey ? charkey:"(null)"));
  787.   pl->count_left=0;
  788.   pl->count=0;
  789.   return 1;
  790. }
  791.  
  792. void handle_keyrelease(object *op,KeyCode kc,KeySym ks)
  793. {
  794.   player *pl = op->contr;
  795.   pl->key_down=0;
  796.  
  797. /* If in ST_MENU_MORE mode, we need to catch the release of shift
  798.  * key, from the user typing shift-a-  A)pply (the menu sign).  Otherwise,
  799.  * the player is frozen in place until shift is pressed again.
  800.  * Mark Wedel (master@cats.ucsc.edu)
  801.  */
  802.  
  803.   if ((kc == pl->firekey[0] && ks == pl->firekeysym[0]) ||
  804.       (kc == pl->firekey[1] && ks == pl->firekeysym[1])) {
  805.     pl->fire_on=0;
  806.     return;
  807.   }
  808.   if ((kc == pl->runkey[0] && ks == pl->runkeysym[0]) ||
  809.       (kc == pl->runkey[1] && ks == pl->runkeysym[1])) {
  810.     pl->run_on=0;
  811.     return;
  812.   }
  813. }
  814.  
  815. void parse_key_release(object *op)
  816. {
  817.   KeyCode kc=op->contr->gevent.xkey.keycode;
  818.   KeySym ks=op->contr->gkey;
  819.  
  820.   handle_keyrelease(op,kc,ks);
  821. }
  822.